﻿using System;
using System.Collections.Generic;
using System.Text;
using HK.Core.Common.Data;
using HK.Core.Common.Protocol;
using HK.Core.Common.Protocol.Data;
using HK.Core.Encryption.Protocol;
using HK.Core.Extend;
using HK.Core.GUIEx.Protocol.Attribute;
using HK.Core.IO.Output;
using HK.Core.Serializable.Attribute;
using HK.Core.Serializable.Data;
using HK.Core.Serializable.Protocol.Data;
using HK.Core.Utils;
using UnityEngine;
using HLogger = HK.Core.Logs.Logger;

namespace HK.Core.Serializable
{
    
    /// <summary>
    /// 序列化资产文件
    /// </summary>
    [Serializable]
    public abstract class SAsset : ScriptableObject, ISAsset
    {

        /// <summary>
        /// 保护构造函数
        /// </summary>
        /// <param name="iStatic">静态文件标志位</param>
        /// <param name="iEditor">编辑器标志位</param>
        /// <param name="iCreateTime">创建时间</param>
        protected SAsset(bool iStatic, bool iEditor = false, long iCreateTime = 0L) : this()
        {
            header = SAssetHeader.Create(iStatic, iEditor, iCreateTime);
        }

        /// <summary>
        /// 保护构造函数
        /// </summary>
        protected SAsset() { }
        
        [SerializeField]
        protected SAssetHeader header = null;
        /// <summary>
        /// 头部信息
        /// </summary>
        public ISAssetHeader Header => header;
        
        /// <summary>
        /// 版本
        /// </summary>
        public ISAssetVersion Version => header?.Version;
        
        /// <summary>
        /// 版本信息 - 短
        /// <para>* 版本格式 : Max.Mid.Min</para>
        /// </summary>
        public string ShortVersion => Version?.Short;
        
        /// <summary>
        /// 版本信息 - All
        /// <para>* 版本格式 : Max.Mid.Min.Tag</para>
        /// </summary>
        public string FullVersion => Version?.Full;

        /// <summary>
        /// 创建时间
        /// <para>* 格式 : YYYY/MM/DD HH:MM:SS</para>
        /// </summary>
        public string CreateTimeTxt => header?.CreateTimeTxt;
        
        /// <summary>
        /// 更新时间
        /// <para>* 格式 : YYYY/MM/DD HH:MM:SS</para>
        /// </summary>
        public string UpdateTimeTxt => header?.UpdateTimeTxt;
        
        /// <summary>
        /// 静态文件标志位
        /// </summary>
        public bool Static
        {
            get => header?.Static ?? false;
            private set
            {
                if(null == header) return;
                header.Static = value;
            }
        }

        /// <summary>
        /// 数据目录
        /// </summary>
        public string DataDir
        {
            get
            {
                if (null == header) return null;
                
                var dstDir = $"{header.Dir}/Data";
                if (!UtilsIo.CheckAndCreateDirByFullDir(dstDir))
                {
                    this.Error("DataDir:UtilsIo.CheckAndCreateDirByFullDir() Failed!(Dir:{0})", dstDir);
                    return null;
                }
                
                return $"{dstDir}/{GetType().Name}";
            }
        }

        /// <summary>
        /// 路径
        /// </summary>
        public string Path => null == header ? "Unknown" : $"{header.Dir}/{GetType().Name}.asset";

#region CheckCode

        [SerializeField, CheckCode("校验码")]
        private string checkCode = null;
        /// <summary>
        /// 校验码
        /// </summary>
        public string CheckCode
        {
            get
            {
                if (!string.IsNullOrEmpty(checkCode)) return checkCode;
                checkCode = GenCheckCode();
                return checkCode;
            }
        }
        
        /// <summary>
        /// 生成校验码
        /// </summary>
        /// <param name="iMode">校验模式(默认:Md5)</param>
        /// <returns>校验码</returns>
        public abstract string GenCheckCode(CheckMode iMode = CheckMode.Md5);

#endregion

#region Path

        /// <summary>
        /// 取得数据文件路径
        /// <para>* 不包含文件后缀名</para>
        /// </summary>
        /// <returns>数据文件路径</returns>
        private string GetDataFilePath() => DataDir;

        /// <summary>
        /// 取得Json文件路径
        /// </summary>
        /// <returns>Json文件路径</returns>
        protected string GetJsonDataFilePath() => $"{GetDataFilePath()}.json";

        /// <summary>
        /// 取得加密文件路径 - Aes
        /// </summary>
        /// <returns>加密文件路径</returns>
        protected string GetAesDataFilePath() => $"{GetDataFilePath()}.aes";

        /// <summary>
        /// 取得加密文件路径 - Des
        /// </summary>
        /// <returns>加密文件路径</returns>
        protected string GetDesDataFilePath() => $"{GetDataFilePath()}.des";

        /// <summary>
        /// 取得Token文件路径
        /// </summary>
        /// <param name="iAlgorithms">Token算法</param>
        /// <returns>Token文件路径</returns>
        protected string GetTokenDataFilePath(TokenAlgorithms iAlgorithms = TokenAlgorithms.Hs256) => $"{GetDataFilePath()}_{iAlgorithms}.token";

#endregion

#region Operation

#region Import

        /// <summary>
        /// 导入
        /// </summary>
        /// <param name="iOptions">选项</param>
        public void Import(int iOptions)
        {
            // 若尚无校验码，则生成校验码
            if (string.IsNullOrEmpty(checkCode))
            {
                checkCode = GenCheckCode();
            }
            
            var flg = false;
            // Json相关的操作
            if (UtilsBytes.CheckBytes(iOptions, (int)SAssetOperateOptions.ImportJson) ||
                UtilsBytes.CheckBytes(iOptions, (int)SAssetOperateOptions.ImportJsonAes) ||
                UtilsBytes.CheckBytes(iOptions, (int)SAssetOperateOptions.ImportJsonDes))
            {
                DoJsonOperateOptions(iOptions, CheckCode);
                flg = true;
            }
            
            // Token相关操作
            if (UtilsBytes.CheckBytes(iOptions, (int)SAssetOperateOptions.ImportTokenHs256) ||
                UtilsBytes.CheckBytes(iOptions, (int)SAssetOperateOptions.ImportTokenHs384) ||
                UtilsBytes.CheckBytes(iOptions, (int)SAssetOperateOptions.ImportTokenHs512))
            {
                DoTokenOperateOptions(iOptions, CheckCode);
                flg = true;
            }
            
            // 二进制相关
            if (UtilsBytes.CheckBytes(iOptions, (int)SAssetOperateOptions.ImportBinary) ||
                UtilsBytes.CheckBytes(iOptions, (int)SAssetOperateOptions.ImportBinaryAes) ||
                UtilsBytes.CheckBytes(iOptions, (int)SAssetOperateOptions.ImportBinaryDes))
            {
                this.Warning("Import():尚未支持二进制导入, 敬请期待!(Options:{0})", iOptions);
                flg = true;
            }
            
            if(flg) return;
            this.Error("Import():Unknown Operation Options:{0}", iOptions);
        }
        
        /// <summary>
        /// 导入 - Json
        /// <para>* 不加密</para>
        /// </summary>
        public void ImportJson() => Import((int)SAssetOperateOptions.ImportJson);

        /// <summary>
        /// 导入 - Json
        /// <para>* Aes</para>
        /// </summary>
        public void ImportJsonAes() => Import((int)SAssetOperateOptions.ImportJsonAes);

        /// <summary>
        /// 导入 - Json
        /// <para>* Des</para>
        /// </summary>
        public void ImportJsonDes() => Import((int)SAssetOperateOptions.ImportJsonDes);
        
        /// <summary>
        /// 导入 - Token
        /// <para>* Hs256</para>
        /// </summary>
        public void ImportTokenHs256() => Import((int)SAssetOperateOptions.ImportTokenHs256);
        
        /// <summary>
        /// 导入 - Token
        /// <para>* Hs384</para>
        /// </summary>
        public void ImportTokenHs384() => Import((int)SAssetOperateOptions.ImportTokenHs384);
        
        /// <summary>
        /// 导入 - Token
        /// <para>* Hs512</para>
        /// </summary>
        public void ImportTokenHs512() => Import((int)SAssetOperateOptions.ImportTokenHs512);

#endregion

#region Export

        /// <summary>
        /// 导出
        /// </summary>
        /// <param name="iOptions">选项</param>
        public void Export(int iOptions)
        {
            // 若尚无校验码，则生成校验码
            if (string.IsNullOrEmpty(checkCode))
            {
                checkCode = GenCheckCode();
            }
            
            var flg = false;
            // Json相关的操作
            if (UtilsBytes.CheckBytes(iOptions, (int)SAssetOperateOptions.ExportJson) ||
                UtilsBytes.CheckBytes(iOptions, (int)SAssetOperateOptions.ExportJsonAes) ||
                UtilsBytes.CheckBytes(iOptions, (int)SAssetOperateOptions.ExportJsonDes))
            {
                DoJsonOperateOptions(iOptions, checkCode);
                flg = true;
            }
            
            // Token相关操作
            if (UtilsBytes.CheckBytes(iOptions, (int)SAssetOperateOptions.ExportTokenHs256) ||
                UtilsBytes.CheckBytes(iOptions, (int)SAssetOperateOptions.ExportTokenHs384) ||
                UtilsBytes.CheckBytes(iOptions, (int)SAssetOperateOptions.ExportTokenHs512))
            {
                DoTokenOperateOptions(iOptions, checkCode);
                flg = true;
            }
            
            // 二进制相关
            if (UtilsBytes.CheckBytes(iOptions, (int)SAssetOperateOptions.ExportBinary) ||
                UtilsBytes.CheckBytes(iOptions, (int)SAssetOperateOptions.ExportBinaryAes) ||
                UtilsBytes.CheckBytes(iOptions, (int)SAssetOperateOptions.ExportBinaryDes))
            {
                this.Warning("Import():尚未支持二进制导出, 敬请期待!(Options:{0})", iOptions);
                flg = true;
            }
            
            if(flg) return;
            this.Error("Export():Unknown Operation Options:{0}", iOptions);
        }
        
        /// <summary>
        /// 导出 - All
        /// </summary>
        public void ExportAll() => Export((int)SAssetOperateOptions.ExportAll);

        /// <summary>
        /// 导入 - Json
        /// <para>* 不加密</para>
        /// </summary>
        public void ExportJson() => Export((int)SAssetOperateOptions.ExportJson);

        /// <summary>
        /// 导入 - Json
        /// <para>* Aes</para>
        /// </summary>
        public void ExportJsonAes() => Export((int)SAssetOperateOptions.ExportJsonAes);

        /// <summary>
        /// 导入 - Json
        /// <para>* Des</para>
        /// </summary>
        public void ExportJsonDes() => Export((int)SAssetOperateOptions.ExportJsonDes);
        
        /// <summary>
        /// 导出 - Token
        /// <para>* Hs256</para>
        /// </summary>
        public void ExportTokenHs256() => Export((int)SAssetOperateOptions.ExportTokenHs256);
        
        /// <summary>
        /// 导出 - Token
        /// <para>* Hs384</para>
        /// </summary>
        public void ExportTokenHs384() => Export((int)SAssetOperateOptions.ExportTokenHs384);
        
        /// <summary>
        /// 导出 - Token
        /// <para>* Hs512</para>
        /// </summary>
        public void ExportTokenHs512() => Export((int)SAssetOperateOptions.ExportTokenHs512);
        
#endregion

#region Clear

        /// <summary>
        /// 清除
        /// </summary>
        public void Clear() => Clear((int)SAssetOperateOptions.Clear);

        /// <summary>
        /// 清除
        /// </summary>
        /// <param name="iOptions">选项</param>
        /// <param name="iForce">强制清空标志位</param>
        public abstract void Clear(int iOptions, bool iForce = false);
        
        /// <summary>
        /// 清除 - All
        /// </summary>
        /// <param name="iForce">强制清空标志位</param>
        public void ClearAll(bool iForce = false) => Clear((int)SAssetOperateOptions.ForceClearAll, iForce);
        
        /// <summary>
        /// 清除 - Json
        /// <para>* 不加密</para>
        /// </summary>
        /// <param name="iForce">强制清空标志位</param>
        public void ClearJson(bool iForce = false) => Clear((int)SAssetOperateOptions.ForceClearJson, iForce);
        
        /// <summary>
        /// 清除 - Json
        /// <para>* Aes</para>
        /// </summary>
        /// <param name="iForce">强制清空标志位</param>
        public void ClearJsonAes(bool iForce = false) => Clear((int)SAssetOperateOptions.ForceClearJsonAes, iForce);
        
        /// <summary>
        /// 清除 - Json
        /// <para>* Des</para>
        /// </summary>
        /// <param name="iForce">强制清空标志位</param>
        public void ClearJsonDes(bool iForce = false) => Clear((int)SAssetOperateOptions.ForceClearJsonDes, iForce);
        
        /// <summary>
        /// 清除 - Token
        /// <para>* Hs256</para>
        /// </summary>
        /// <param name="iForce">强制清空标志位</param>
        public void ClearTokenHs256(bool iForce = false) => Clear((int)SAssetOperateOptions.ForceClearTokenHs256, iForce);
        
        /// <summary>
        /// 清除 - Token
        /// <para>* Hs384</para>
        /// </summary>
        /// <param name="iForce">强制清空标志位</param>
        public void ClearTokenHs384(bool iForce = false) => Clear((int)SAssetOperateOptions.ForceClearTokenHs384, iForce);
        
        /// <summary>
        /// 清除 - Token
        /// <para>* Hs512</para>
        /// </summary>
        /// <param name="iForce">强制清空标志位</param>
        public void ClearTokenHs512(bool iForce = false) => Clear((int)SAssetOperateOptions.ForceClearTokenHs512, iForce);

#endregion

        /// <summary>
        /// Json相关的操作
        /// </summary>
        /// <param name="iOptions">操作选项</param>
        /// <param name="iSecretKey">密钥</param>
        protected abstract void DoJsonOperateOptions(int iOptions, string iSecretKey = null);

        /// <summary>
        /// Token相关的操作
        /// </summary>
        /// <param name="iOptions">操作选项</param>
        /// <param name="iSecretKey">密钥</param>
        protected abstract void DoTokenOperateOptions(int iOptions, string iSecretKey = null);

#endregion
        
        /// <summary>
        /// 刷新
        /// </summary>
        public virtual void Refresh()
        {
            header?.Refresh();
        }
        
    }

    /// <summary>
    /// 序列化资产文件
    /// </summary>
    /// <typeparam name="TAsset">序列化资产文件类型</typeparam>
    /// <typeparam name="TBody">资产文件Body数据类型</typeparam>
    [Serializable]
    public class SAsset<TAsset, TBody> : SAsset, ISAsset<TBody>
        where TAsset : SAsset
        where TBody : SAssetData, new()
    {

#region Static

        private static TAsset _instance = default(TAsset);

        /// <summary>
        /// 实例
        /// </summary>
        public static TAsset Instance
        {
            get
            {
                if (default(TAsset) != _instance) return _instance;
                _instance = UtilsSAssets.LoadAssetSync<TAsset>();
                if (string.IsNullOrEmpty(_instance.CheckCode))
                {
                    HLogger.Error($"{typeof(TAsset).Name}::校验码生成失败!");
                }
                return _instance;
            }
        }

#endregion
        
        /// <summary>
        /// 保护构造函数
        /// </summary>
        /// <param name="iStatic">静态文件标志位</param>
        /// <param name="iCreateTime">创建时间</param>
        protected SAsset(bool iStatic, long iCreateTime = 0L) : base(iStatic, false, iCreateTime) { }
        
        /// <summary>
        /// 保护构造函数
        /// </summary>
        private SAsset() { }
        
#region Data

        [SerializeField, SBody("设定")]
        private TBody body = new TBody();
        /// <summary>
        /// 序列化数据 - Body
        /// </summary>
        public TBody Body => body;

#endregion

#region CheckCode

        /// <summary>
        /// 生成校验码
        /// </summary>
        /// <param name="iMode">校验模式(默认:Md5)</param>
        /// <returns>校验码</returns>
        public override string GenCheckCode(CheckMode iMode = CheckMode.Md5)
        {
            Header.Refresh();
            return UtilsCheckCode.Encode(header, iMode, false);
        }

#endregion

#region Operation

        /// <summary>
        /// Json相关的操作
        /// </summary>
        /// <param name="iOptions">操作选项</param>
        /// <param name="iSecretKey">密钥</param>
        protected override void DoJsonOperateOptions(int iOptions, string iSecretKey = null)
        {
            // 导入 - Json/不加密
            if (UtilsBytes.CheckBytes(iOptions, (int)SAssetOperateOptions.ImportJson))
            {
                var jsonPath = GetJsonDataFilePath();
                var jsonFileIo = JsonFileIO<TBody>.Create(Body, jsonPath);
                jsonFileIo?.Import((iSucceeded) =>
                {
                    if(!iSucceeded) return;

                    // 应用数据
                    var dirty = Body.ApplyData(jsonFileIo.Data);
                    if (dirty)
                    {
                        Refresh();
                    }
                });
                return;
            }
            
            // 导入 - Json/Aes
            if (UtilsBytes.CheckBytes(iOptions, (int)SAssetOperateOptions.ImportJsonAes))
            {
                var aesPath = GetAesDataFilePath();
                var aesFileIo = JsonAesFileIO<TBody>.Create(Body, Encoding.UTF8, aesPath, iSecretKey);
                aesFileIo?.Import((iSucceeded) =>
                {
                    if(!iSucceeded) return;

                    // 应用数据
                    var dirty = Body.ApplyData(aesFileIo.Data);
                    if (dirty)
                    {
                        Refresh();
                    }
                });
                return;
            }
            
            // 导入 - Json/Des
            if (UtilsBytes.CheckBytes(iOptions, (int)SAssetOperateOptions.ImportJsonDes))
            {
                var aesPath = GetDesDataFilePath();
                var aesFileIo = JsonDesFileIO<TBody>.Create(Body, Encoding.UTF8, aesPath, iSecretKey);
                aesFileIo?.Import((iSucceeded) =>
                {
                    if(!iSucceeded) return;

                    // 应用数据
                    var dirty = Body.ApplyData(aesFileIo.Data);
                    if (dirty)
                    {
                        Refresh();
                    }
                });
                return;
            }
            
            // 导出 - Json/不加密
            if (UtilsBytes.CheckBytes(iOptions, (int)SAssetOperateOptions.ExportJson))
            {
                var jsonPath = GetJsonDataFilePath();
                var jsonFileIo = JsonFileIO<TBody>.Create(Body, jsonPath);
                jsonFileIo?.Export((iSucceeded) =>
                {
                    if(!iSucceeded) return;
                    // Dirty = true;
                });
            }
            
            // 导出 - Json/Aes
            if (UtilsBytes.CheckBytes(iOptions, (int)SAssetOperateOptions.ExportJsonAes))
            {
                var aesPath = GetAesDataFilePath();
                var aesFileIo = JsonAesFileIO<TBody>.Create(Body, Encoding.UTF8, aesPath, iSecretKey);
                aesFileIo?.Export((iSucceeded) =>
                {
                    if(!iSucceeded) return;
                    // Dirty = true;
                });
            }
            
            // 导出 - Json/Des
            if (UtilsBytes.CheckBytes(iOptions, (int)SAssetOperateOptions.ExportJsonDes))
            {
                var aesPath = GetDesDataFilePath();
                var aesFileIo = JsonDesFileIO<TBody>.Create(Body, Encoding.UTF8, aesPath, iSecretKey);
                aesFileIo?.Export((iSucceeded) =>
                {
                    if(!iSucceeded) return;
                    // Dirty = true;
                });
            }
            
            // 强制清空 - Json/不加密
            if (UtilsBytes.CheckBytes(iOptions, (int)SAssetOperateOptions.ForceClearJson))
            {
                var jsonPath = GetJsonDataFilePath();
                var jsonFileIo = JsonFileIO<TBody>.Create(Body, jsonPath);
                var dirty = jsonFileIo?.Clear(true) ?? false;
                if (dirty)
                {
                    Refresh();
                }
            }
            
            // 强制清空 - Json/Aes
            if (UtilsBytes.CheckBytes(iOptions, (int)SAssetOperateOptions.ForceClearJsonAes))
            {
                var aesPath = GetAesDataFilePath();
                var aesFileIo = JsonAesFileIO<TBody>.Create(Body, Encoding.UTF8, aesPath, iSecretKey);
                var dirty = aesFileIo?.Clear(true) ?? false;
                if (dirty)
                {
                    Refresh();
                }
            }
            
            // 强制清空 - Json/Des
            if (UtilsBytes.CheckBytes(iOptions, (int)SAssetOperateOptions.ForceClearJsonDes))
            {
                var aesPath = GetDesDataFilePath();
                var aesFileIo = JsonDesFileIO<TBody>.Create(Body, Encoding.UTF8, aesPath, iSecretKey);
                var dirty = aesFileIo?.Clear(true) ?? false;
                if (dirty)
                {
                    Refresh();
                }
            }
        }
        
        /// <summary>
        /// Token相关的操作
        /// </summary>
        /// <param name="iOptions">操作选项</param>
        /// <param name="iSecretKey">密钥</param>
        protected override void DoTokenOperateOptions(int iOptions, string iSecretKey = null)
        {
            
            // 导入 - Token - Hs256
            if (UtilsBytes.CheckBytes(iOptions, (int)SAssetOperateOptions.ImportTokenHs256))
            {
                var tokenPath = GetTokenDataFilePath(TokenAlgorithms.Hs256);
                var tokenFileIo = TokenFileIO<TBody>.Create(Body, Encoding.UTF8, tokenPath, iSecretKey, TokenAlgorithms.Hs256);
                tokenFileIo?.Import((iSucceeded) =>
                {
                    if(!iSucceeded) return;

                    // 应用数据
                    var dirty = Body.ApplyData(tokenFileIo.Data);
                    if (dirty)
                    {
                        Refresh();
                    }
                });
                return;
            }
            
            // 导入 - Token - Hs384
            if (UtilsBytes.CheckBytes(iOptions, (int)SAssetOperateOptions.ImportTokenHs384))
            {
                var tokenPath = GetTokenDataFilePath(TokenAlgorithms.Hs384);
                var tokenFileIo = TokenFileIO<TBody>.Create(Body, Encoding.UTF8, tokenPath, iSecretKey, TokenAlgorithms.Hs384);
                tokenFileIo?.Import((iSucceeded) =>
                {
                    if(!iSucceeded) return;

                    // 应用数据
                    var dirty = Body.ApplyData(tokenFileIo.Data);
                    if (dirty)
                    {
                        Refresh();
                    }
                });
                return;
            }
            
            // 导入 - Token - Hs512
            if (UtilsBytes.CheckBytes(iOptions, (int)SAssetOperateOptions.ImportTokenHs512))
            {
                var tokenPath = GetTokenDataFilePath(TokenAlgorithms.Hs512);
                var tokenFileIo = TokenFileIO<TBody>.Create(Body, Encoding.UTF8, tokenPath, iSecretKey, TokenAlgorithms.Hs512);
                tokenFileIo?.Import((iSucceeded) =>
                {
                    if(!iSucceeded) return;

                    // 应用数据
                    var dirty = Body.ApplyData(tokenFileIo.Data);
                    if (dirty)
                    {
                        Refresh();
                    }
                });
                return;
            }
            
            // 导出 - Token - Hs256
            if (UtilsBytes.CheckBytes(iOptions, (int)SAssetOperateOptions.ExportTokenHs256))
            {
                var tokenPath = GetTokenDataFilePath(TokenAlgorithms.Hs256);
                var tokenFileIo = TokenFileIO<TBody>.Create(Body, Encoding.UTF8, tokenPath, iSecretKey, TokenAlgorithms.Hs256);
                tokenFileIo?.Export((iSucceeded) =>
                {
                    if(!iSucceeded) return;
                    // Dirty = true;
                });
            }
            
            // 导出 - Token - Hs384
            if (UtilsBytes.CheckBytes(iOptions, (int)SAssetOperateOptions.ExportTokenHs384))
            {
                var tokenPath = GetTokenDataFilePath(TokenAlgorithms.Hs384);
                var tokenFileIo = TokenFileIO<TBody>.Create(Body, Encoding.UTF8, tokenPath, iSecretKey, TokenAlgorithms.Hs384);
                tokenFileIo?.Export((iSucceeded) =>
                {
                    if(!iSucceeded) return;
                    // Dirty = true;
                });
            }
            
            // 导出 - Token - Hs512
            if (UtilsBytes.CheckBytes(iOptions, (int)SAssetOperateOptions.ExportTokenHs512))
            {
                var tokenPath = GetTokenDataFilePath(TokenAlgorithms.Hs512);
                var tokenFileIo = TokenFileIO<TBody>.Create(Body, Encoding.UTF8, tokenPath, iSecretKey, TokenAlgorithms.Hs512);
                tokenFileIo?.Export((iSucceeded) =>
                {
                    if(!iSucceeded) return;
                    // Dirty = true;
                });
            }
            
            // 强制清空 - Token - Hs256
            if (UtilsBytes.CheckBytes(iOptions, (int)SAssetOperateOptions.ForceClearTokenHs256))
            {
                var tokenPath = GetTokenDataFilePath(TokenAlgorithms.Hs256);
                var tokenFileIo = TokenFileIO<TBody>.Create(Body, Encoding.UTF8, tokenPath, iSecretKey, TokenAlgorithms.Hs256);
                var dirty = tokenFileIo?.Clear(true) ?? false;
                if (dirty)
                {
                    Refresh();
                }
            }
            
            // 强制清空 - Token - Hs384
            if (UtilsBytes.CheckBytes(iOptions, (int)SAssetOperateOptions.ForceClearTokenHs384))
            {
                var tokenPath = GetTokenDataFilePath(TokenAlgorithms.Hs384);
                var tokenFileIo = TokenFileIO<TBody>.Create(Body, Encoding.UTF8, tokenPath, iSecretKey, TokenAlgorithms.Hs384);
                var dirty = tokenFileIo?.Clear(true) ?? false;
                if (dirty)
                {
                    Refresh();
                }
            }
            
            // 强制清空 - Token - Hs512
            if (UtilsBytes.CheckBytes(iOptions, (int)SAssetOperateOptions.ForceClearTokenHs512))
            {
                var tokenPath = GetTokenDataFilePath(TokenAlgorithms.Hs512);
                var tokenFileIo = TokenFileIO<TBody>.Create(Body, Encoding.UTF8, tokenPath, iSecretKey, TokenAlgorithms.Hs512);
                var dirty = tokenFileIo?.Clear(true) ?? false;
                if (dirty)
                {
                    Refresh();
                }
            }
        }

#region Clear

        /// <summary>
        /// 清除
        /// </summary>
        /// <param name="iOptions">选项</param>
        /// <param name="iForce">强制清空标志位</param>
        public override void Clear(int iOptions, bool iForce = false)
        {
            // 清空
            if(UtilsBytes.CheckBytes(iOptions, (int)SAssetOperateOptions.Clear))
            {
                Body?.Clear();
                return;
            }
            
            var flg = false;
            // Json相关的操作
            if (UtilsBytes.CheckBytes(iOptions, (int)SAssetOperateOptions.ForceClearJson) ||
                UtilsBytes.CheckBytes(iOptions, (int)SAssetOperateOptions.ForceClearJsonAes) ||
                UtilsBytes.CheckBytes(iOptions, (int)SAssetOperateOptions.ForceClearJsonDes))
            {
                DoJsonOperateOptions(iOptions);
                flg = true;
            }
            
            // Token相关操作
            if (UtilsBytes.CheckBytes(iOptions, (int)SAssetOperateOptions.ForceClearTokenHs256) ||
                UtilsBytes.CheckBytes(iOptions, (int)SAssetOperateOptions.ForceClearTokenHs384) ||
                UtilsBytes.CheckBytes(iOptions, (int)SAssetOperateOptions.ForceClearTokenHs512))
            {
                DoTokenOperateOptions(iOptions);
                flg = true;
            }
            
            // 二进制相关
            if (UtilsBytes.CheckBytes(iOptions, (int)SAssetOperateOptions.ForceClearBinary) ||
                UtilsBytes.CheckBytes(iOptions, (int)SAssetOperateOptions.ForceClearBinaryAes) ||
                UtilsBytes.CheckBytes(iOptions, (int)SAssetOperateOptions.ForceClearBinaryDes))
            {
                this.Warning("Import():尚未支持二进制强制清空, 敬请期待!(Options:{0})", iOptions);
                flg = true;
            }
            
            if(flg) return;
            this.Error("Clear():Unknown Operation Options:{0}", iOptions);
        }

#endregion

#endregion
        
    }

    /// <summary>
    /// 序列化资产文件
    /// </summary>
    /// <typeparam name="TAsset">序列化资产文件类型</typeparam>
    /// <typeparam name="TBody">列表数据类型</typeparam>
    /// <typeparam name="TElement">列表Element数据类型</typeparam>
    [Serializable]
    public class SAssetList<TAsset, TBody, TElement> : SAsset, ISAssetList<TBody, TElement>
        where TAsset : SAsset
        where TBody : SAssetListData<TBody, TElement>, new()
        where TElement : JsonData, IListElement, IEquatable<TElement>
    {
#region Static

        private static TAsset _instance = default(TAsset);

        /// <summary>
        /// 实例
        /// </summary>
        public static TAsset Instance
        {
            get
            {
                if (default(TAsset) != _instance) return _instance;
                _instance = UtilsSAssets.LoadAssetSync<TAsset>();
                return _instance;
            }
        }

#endregion

        /// <summary>
        /// 保护构造函数
        /// </summary>
        /// <param name="iStatic">静态文件标志位</param>
        /// <param name="iCreateTime">创建时间</param>
        protected SAssetList(bool iStatic, long iCreateTime = 0L) : base(iStatic, false, iCreateTime) { }

#region Data

        [SerializeField, ListView("列表", "sceneName", (int)GUIOperateOptions.DefaultPagination, 30, true,false)]
        private TBody body = new TBody();
        /// <summary>
        /// 序列化数据 - Body
        /// </summary>
        public TBody Body => body;
        
        /// <summary>
        /// 列表
        /// </summary>
        public List<TElement> List => body.List;

#endregion
        
#region CheckCode

        /// <summary>
        /// 生成校验码
        /// </summary>
        /// <param name="iMode">校验模式(默认:Md5)</param>
        /// <returns>校验码</returns>
        public override string GenCheckCode(CheckMode iMode = CheckMode.Md5)
        {
            Header.Refresh();
            return UtilsCheckCode.Encode(header, iMode, false);
        }

#endregion



#region Operation

        /// <summary>
        /// Json相关的操作
        /// </summary>
        /// <param name="iOptions">操作选项</param>
        /// <param name="iSecretKey">密钥</param>
        protected override void DoJsonOperateOptions(int iOptions, string iSecretKey = null)
        {
            // 导入 - Json/不加密
            if (UtilsBytes.CheckBytes(iOptions, (int)SAssetOperateOptions.ImportJson))
            {
                var jsonPath = GetJsonDataFilePath();
                var jsonFileIo = JsonFileIO<TBody>.Create(Body, jsonPath);
                jsonFileIo?.Import((iSucceeded) =>
                {
                    if(!iSucceeded) return;

                    // 应用数据
                    var dirty = Body.ApplyData(jsonFileIo.Data);
                    if (dirty)
                    {
                        Refresh();
                    }
                });
                return;
            }
            
            // 导入 - Json/Aes
            if (UtilsBytes.CheckBytes(iOptions, (int)SAssetOperateOptions.ImportJsonAes))
            {
                var aesPath = GetAesDataFilePath();
                var aesFileIo = JsonAesFileIO<TBody>.Create(Body, Encoding.UTF8, aesPath, iSecretKey);
                aesFileIo?.Import((iSucceeded) =>
                {
                    if(!iSucceeded) return;

                    // 应用数据
                    var dirty = Body.ApplyData(aesFileIo.Data);
                    if (dirty)
                    {
                        Refresh();
                    }
                });
                return;
            }
            
            // 导入 - Json/Des
            if (UtilsBytes.CheckBytes(iOptions, (int)SAssetOperateOptions.ImportJsonDes))
            {
                var aesPath = GetDesDataFilePath();
                var aesFileIo = JsonDesFileIO<TBody>.Create(Body, Encoding.UTF8, aesPath, iSecretKey);
                aesFileIo?.Import((iSucceeded) =>
                {
                    if(!iSucceeded) return;

                    // 应用数据
                    var dirty = Body.ApplyData(aesFileIo.Data);
                    if (dirty)
                    {
                        Refresh();
                    }
                });
                return;
            }
            
            // 导出 - Json/不加密
            if (UtilsBytes.CheckBytes(iOptions, (int)SAssetOperateOptions.ExportJson))
            {
                var jsonPath = GetJsonDataFilePath();
                var jsonFileIo = JsonFileIO<TBody>.Create(Body, jsonPath);
                jsonFileIo?.Export((iSucceeded) =>
                {
                    if(!iSucceeded) return;
                    // Dirty = true;
                });
            }
            
            // 导出 - Json/Aes
            if (UtilsBytes.CheckBytes(iOptions, (int)SAssetOperateOptions.ExportJsonAes))
            {
                var aesPath = GetAesDataFilePath();
                var aesFileIo = JsonAesFileIO<TBody>.Create(Body, Encoding.UTF8, aesPath, iSecretKey);
                aesFileIo?.Export((iSucceeded) =>
                {
                    if(!iSucceeded) return;
                    // Dirty = true;
                });
            }
            
            // 导出 - Json/Des
            if (UtilsBytes.CheckBytes(iOptions, (int)SAssetOperateOptions.ExportJsonDes))
            {
                var aesPath = GetDesDataFilePath();
                var aesFileIo = JsonDesFileIO<TBody>.Create(Body, Encoding.UTF8, aesPath, iSecretKey);
                aesFileIo?.Export((iSucceeded) =>
                {
                    if(!iSucceeded) return;
                    // Dirty = true;
                });
            }
            
            // 强制清空 - Json/不加密
            if (UtilsBytes.CheckBytes(iOptions, (int)SAssetOperateOptions.ForceClearJson))
            {
                var jsonPath = GetJsonDataFilePath();
                var jsonFileIo = JsonFileIO<TBody>.Create(Body, jsonPath);
                var dirty = jsonFileIo?.Clear(true) ?? false;
                if (dirty)
                {
                    Refresh();
                }
            }
            
            // 强制清空 - Json/Aes
            if (UtilsBytes.CheckBytes(iOptions, (int)SAssetOperateOptions.ForceClearJsonAes))
            {
                var aesPath = GetAesDataFilePath();
                var aesFileIo = JsonAesFileIO<TBody>.Create(Body, Encoding.UTF8, aesPath, iSecretKey);
                var dirty = aesFileIo?.Clear(true) ?? false;
                if (dirty)
                {
                    Refresh();
                }
            }
            
            // 强制清空 - Json/Des
            if (UtilsBytes.CheckBytes(iOptions, (int)SAssetOperateOptions.ForceClearJsonDes))
            {
                var aesPath = GetDesDataFilePath();
                var aesFileIo = JsonDesFileIO<TBody>.Create(Body, Encoding.UTF8, aesPath, iSecretKey);
                var dirty = aesFileIo?.Clear(true) ?? false;
                if (dirty)
                {
                    Refresh();
                }
            }
        }
        
        /// <summary>
        /// Token相关的操作
        /// </summary>
        /// <param name="iOptions">操作选项</param>
        /// <param name="iSecretKey">密钥</param>
        protected override void DoTokenOperateOptions(int iOptions, string iSecretKey = null)
        {
            
            // 导入 - Token - Hs256
            if (UtilsBytes.CheckBytes(iOptions, (int)SAssetOperateOptions.ImportTokenHs256))
            {
                var tokenPath = GetTokenDataFilePath(TokenAlgorithms.Hs256);
                var tokenFileIo = TokenFileIO<TBody>.Create(Body, Encoding.UTF8, tokenPath, iSecretKey, TokenAlgorithms.Hs256);
                tokenFileIo?.Import((iSucceeded) =>
                {
                    if(!iSucceeded) return;

                    // 应用数据
                    var dirty = Body.ApplyData(tokenFileIo.Data);
                    if (dirty)
                    {
                        Refresh();
                    }
                });
                return;
            }
            
            // 导入 - Token - Hs384
            if (UtilsBytes.CheckBytes(iOptions, (int)SAssetOperateOptions.ImportTokenHs384))
            {
                var tokenPath = GetTokenDataFilePath(TokenAlgorithms.Hs384);
                var tokenFileIo = TokenFileIO<TBody>.Create(Body, Encoding.UTF8, tokenPath, iSecretKey, TokenAlgorithms.Hs384);
                tokenFileIo?.Import((iSucceeded) =>
                {
                    if(!iSucceeded) return;

                    // 应用数据
                    var dirty = Body.ApplyData(tokenFileIo.Data);
                    if (dirty)
                    {
                        Refresh();
                    }
                });
                return;
            }
            
            // 导入 - Token - Hs512
            if (UtilsBytes.CheckBytes(iOptions, (int)SAssetOperateOptions.ImportTokenHs512))
            {
                var tokenPath = GetTokenDataFilePath(TokenAlgorithms.Hs512);
                var tokenFileIo = TokenFileIO<TBody>.Create(Body, Encoding.UTF8, tokenPath, iSecretKey, TokenAlgorithms.Hs512);
                tokenFileIo?.Import((iSucceeded) =>
                {
                    if(!iSucceeded) return;

                    // 应用数据
                    var dirty = Body.ApplyData(tokenFileIo.Data);
                    if (dirty)
                    {
                        Refresh();
                    }
                });
                return;
            }
            
            // 导出 - Token - Hs256
            if (UtilsBytes.CheckBytes(iOptions, (int)SAssetOperateOptions.ExportTokenHs256))
            {
                var tokenPath = GetTokenDataFilePath(TokenAlgorithms.Hs256);
                var tokenFileIo = TokenFileIO<TBody>.Create(Body, Encoding.UTF8, tokenPath, iSecretKey, TokenAlgorithms.Hs256);
                tokenFileIo?.Export((iSucceeded) =>
                {
                    if(!iSucceeded) return;
                    // Dirty = true;
                });
            }
            
            // 导出 - Token - Hs384
            if (UtilsBytes.CheckBytes(iOptions, (int)SAssetOperateOptions.ExportTokenHs384))
            {
                var tokenPath = GetTokenDataFilePath(TokenAlgorithms.Hs384);
                var tokenFileIo = TokenFileIO<TBody>.Create(Body, Encoding.UTF8, tokenPath, iSecretKey, TokenAlgorithms.Hs384);
                tokenFileIo?.Export((iSucceeded) =>
                {
                    if(!iSucceeded) return;
                    // Dirty = true;
                });
            }
            
            // 导出 - Token - Hs512
            if (UtilsBytes.CheckBytes(iOptions, (int)SAssetOperateOptions.ExportTokenHs512))
            {
                var tokenPath = GetTokenDataFilePath(TokenAlgorithms.Hs512);
                var tokenFileIo = TokenFileIO<TBody>.Create(Body, Encoding.UTF8, tokenPath, iSecretKey, TokenAlgorithms.Hs512);
                tokenFileIo?.Export((iSucceeded) =>
                {
                    if(!iSucceeded) return;
                    // Dirty = true;
                });
            }
            
            // 强制清空 - Token - Hs256
            if (UtilsBytes.CheckBytes(iOptions, (int)SAssetOperateOptions.ForceClearTokenHs256))
            {
                var tokenPath = GetTokenDataFilePath(TokenAlgorithms.Hs256);
                var tokenFileIo = TokenFileIO<TBody>.Create(Body, Encoding.UTF8, tokenPath, iSecretKey, TokenAlgorithms.Hs256);
                var dirty = tokenFileIo?.Clear(true) ?? false;
                if (dirty)
                {
                    Refresh();
                }
            }
            
            // 强制清空 - Token - Hs384
            if (UtilsBytes.CheckBytes(iOptions, (int)SAssetOperateOptions.ForceClearTokenHs384))
            {
                var tokenPath = GetTokenDataFilePath(TokenAlgorithms.Hs384);
                var tokenFileIo = TokenFileIO<TBody>.Create(Body, Encoding.UTF8, tokenPath, iSecretKey, TokenAlgorithms.Hs384);
                var dirty = tokenFileIo?.Clear(true) ?? false;
                if (dirty)
                {
                    Refresh();
                }
            }
            
            // 强制清空 - Token - Hs512
            if (UtilsBytes.CheckBytes(iOptions, (int)SAssetOperateOptions.ForceClearTokenHs512))
            {
                var tokenPath = GetTokenDataFilePath(TokenAlgorithms.Hs512);
                var tokenFileIo = TokenFileIO<TBody>.Create(Body, Encoding.UTF8, tokenPath, iSecretKey, TokenAlgorithms.Hs512);
                var dirty = tokenFileIo?.Clear(true) ?? false;
                if (dirty)
                {
                    Refresh();
                }
            }
        }

#region Clear

        /// <summary>
        /// 清除
        /// </summary>
        /// <param name="iOptions">选项</param>
        /// <param name="iForce">强制清空标志位</param>
        public override void Clear(int iOptions, bool iForce = false)
        {
            // 清空
            if(UtilsBytes.CheckBytes(iOptions, (int)SAssetOperateOptions.Clear))
            {
                Body?.Clear();
                return;
            }
            
            var flg = false;
            // Json相关的操作
            if (UtilsBytes.CheckBytes(iOptions, (int)SAssetOperateOptions.ForceClearJson) ||
                UtilsBytes.CheckBytes(iOptions, (int)SAssetOperateOptions.ForceClearJsonAes) ||
                UtilsBytes.CheckBytes(iOptions, (int)SAssetOperateOptions.ForceClearJsonDes))
            {
                DoJsonOperateOptions(iOptions);
                flg = true;
            }
            
            // Token相关操作
            if (UtilsBytes.CheckBytes(iOptions, (int)SAssetOperateOptions.ForceClearTokenHs256) ||
                UtilsBytes.CheckBytes(iOptions, (int)SAssetOperateOptions.ForceClearTokenHs384) ||
                UtilsBytes.CheckBytes(iOptions, (int)SAssetOperateOptions.ForceClearTokenHs512))
            {
                DoTokenOperateOptions(iOptions);
                flg = true;
            }
            
            // 二进制相关
            if (UtilsBytes.CheckBytes(iOptions, (int)SAssetOperateOptions.ForceClearBinary) ||
                UtilsBytes.CheckBytes(iOptions, (int)SAssetOperateOptions.ForceClearBinaryAes) ||
                UtilsBytes.CheckBytes(iOptions, (int)SAssetOperateOptions.ForceClearBinaryDes))
            {
                this.Warning("Import():尚未支持二进制强制清空, 敬请期待!(Options:{0})", iOptions);
                flg = true;
            }
            
            if(flg) return;
            this.Error("Clear():Unknown Operation Options:{0}", iOptions);
        }

#endregion

#endregion

    }
}